﻿/*******************************************************************************
 * Level Master 2000
 * Copyright (C) 2010 Christian Herzog
 * For more information see http://code.google.com/p/levelmaster2000/
 *
 * This file is licensed under the terms of the MIT license, see
 * http://www.opensource.org/licenses/mit-license.php for further information.
 ******************************************************************************/

package
{
    import com.pblabs.box2D.*;
    import com.pblabs.box2D.Box2DDebugComponent;
    import com.pblabs.box2D.Box2DManagerComponent;
    import com.pblabs.box2D.Box2DSpatialComponent;
    import com.pblabs.box2D.CircleCollisionShape;
    import com.pblabs.box2D.PolygonCollisionShape;
    import com.pblabs.components.basic.HealthComponent;
    import com.pblabs.engine.core.*;
    import com.pblabs.engine.core.LevelManager;
    import com.pblabs.engine.entity.*;
    import com.pblabs.engine.entity.IEntity;
    import com.pblabs.engine.PBE;
    import com.pblabs.engine.resource.ImageResource;
    import com.pblabs.rendering2D.*;
    import com.pblabs.rendering2D.DisplayObjectScene;
    import com.pblabs.rendering2D.SpriteSheetRenderer;
    import com.pblabs.rendering2D.ui.*;
    import com.pblabs.rendering2D.ui.SceneView;
    import com.wyrmtale.pbe.ScrollingBitmapRenderer;
    import com.zog.Box2DTrigger;
    import com.zog.DamageEntityOnCollision;
    import com.zog.DestroyEntityOnCollision;
    import com.zog.EntitySpawner;
    import com.zog.RandomNumber;
    import com.zog.RandomPoint;
    import com.zog.SpaceShipController;
    import com.zog.SpaceShipLogic;
    import flash.display.*;
    import flash.display.Sprite;
    import flash.events.*;
    import flash.external.ExternalInterface;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    import flash.system.Security;
    import flash.utils.*;
    
    [SWF(width="800", height="600", frameRate="60", backgroundColor="#08d4f8")]
    public class Demo extends Sprite
    {      
        public function Demo() 
        {
            Security.allowDomain("*");
            
            // Make sure all the types our XML will use are registered.
            PBE.registerType(flash.geom.Point);
            PBE.registerType(flash.geom.Matrix);
            PBE.registerType(flash.geom.Rectangle);
            PBE.registerType(flash.geom.Transform);

            PBE.registerType(com.pblabs.engine.PBE);
            PBE.registerType(com.pblabs.engine.core.LevelManager);
            
            PBE.registerType(com.pblabs.rendering2D.SpriteRenderer);
            PBE.registerType(com.pblabs.rendering2D.DisplayObjectScene);
            PBE.registerType(com.pblabs.rendering2D.SpriteSheetRenderer);
            PBE.registerType(com.pblabs.rendering2D.ui.SceneView);

            PBE.registerType(com.pblabs.box2D.Box2DDebugComponent);
            PBE.registerType(com.pblabs.box2D.Box2DManagerComponent);
            PBE.registerType(com.pblabs.box2D.Box2DSpatialComponent);
            PBE.registerType(com.pblabs.box2D.PolygonCollisionShape);
            PBE.registerType(com.pblabs.box2D.CircleCollisionShape);
        
            PBE.registerType(ImageResource);
            PBE.registerType(RandomNumber);
            PBE.registerType(RandomPoint);
            PBE.registerType(EntitySpawner);
            PBE.registerType(SpaceShipLogic);
            PBE.registerType(DestroyEntityOnCollision);
            PBE.registerType(SpaceShipController);
            PBE.registerType(HealthComponent);
            PBE.registerType(Box2DTrigger);

            if (this.stage)
            {
                onAddedToStage();
            } 
            else 
            {
                addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
            }
        }

        private function createBox2DDebugView():void
        {
            if(PBE.nameManager.lookup("DEBUG") == null)
            {
                var e:IEntity = PBE.allocateEntity();
                e.initialize("DEBUG");

                var c:Box2DDebugComponent = new Box2DDebugComponent();
                c.spatialManager = PBE.spatialManager as Box2DManagerComponent;
                c.scene = PBE.scene;
                
                e.addComponent(c, "visual");
            }
        }

        private function createBullet():IEntity
        {
            var entity:IEntity = PBE.allocateEntity();
            var entName:String = PBE.nameManager.validateName("Bullet");
            entity.initialize(entName);

            //Create our spatial component / body:
            var spatialComp:Box2DSpatialComponent = new Box2DSpatialComponent();
            spatialComp.spatialManager= PBE.spatialManager as Box2DManagerComponent;
            spatialComp.position = new Point(-1000, -1000);
            spatialComp.size = new Point(8, 8);
            spatialComp.collisionType = new ObjectType("Bullet");
            spatialComp.canMove = true;
            spatialComp.canRotate = false;
            spatialComp.canSleep = true;
            spatialComp.collidesWithTypes = new ObjectType("Asteroid", "WorldBounds");
            
            var shape:PolygonCollisionShape = new PolygonCollisionShape();
            shape.friction = 0.0;
            shape.vertices = new Array();
            shape.vertices.push( new Point( -1, -1) );
            shape.vertices.push( new Point( 1, -1) );
            shape.vertices.push( new Point( 1, 1) );
            shape.vertices.push( new Point( -1, 1) );
            shape.density = 1.0;

            //Now we add the shape to the spatial component / body:
            spatialComp.collisionShapes = new Array();
            spatialComp.collisionShapes.push(shape);
             
            //Add the component to the entity:
            entity.addComponent( spatialComp, "Spatial" ); 			

			//Since we want to visualize the entity, we need a simple sprite renderer:
			var renderComp:SpriteRenderer = new SpriteRenderer(); 

			renderComp.scene = PBE.scene;
			renderComp.fileName = "../space/Images/bullet.png";
			renderComp.positionProperty  = new PropertyReference("@Spatial.position");
            renderComp.zIndex = 100;

			//Add the component to the entity:
			entity.addComponent( renderComp, "Render" )
            
            var destroyOnCollision:DestroyEntityOnCollision = new DestroyEntityOnCollision();
            entity.addComponent(destroyOnCollision, "DestroyOnCollision");            

            return entity;
        }
        
        private function createAsteroid():IEntity
        {
            var entity:IEntity = PBE.allocateEntity();
            var entName:String = PBE.nameManager.validateName("Asteroid");
            entity.initialize(entName);

            //Create our spatial component / body:
            var spatialComp:Box2DSpatialComponent = new Box2DSpatialComponent();
            spatialComp.spatialManager= PBE.spatialManager as Box2DManagerComponent;
            spatialComp.position = new Point(-1000, -1000);
            spatialComp.size = new Point(32, 32);
            spatialComp.collisionType = new ObjectType("Asteroid");
            spatialComp.canMove = true;
            spatialComp.canRotate = true;
            spatialComp.canSleep = true;
            spatialComp.collidesWithTypes = new ObjectType("Player", "WorldBounds", "Bullet");
            
            var shape:PolygonCollisionShape = new PolygonCollisionShape();
            shape.friction = 0.0;
            shape.vertices = new Array();
            shape.vertices.push( new Point( -1, -1) );
            shape.vertices.push( new Point( 1, -1) );
            shape.vertices.push( new Point( 1, 1) );
            shape.vertices.push( new Point( -1, 1) );
            shape.density = 1.0;

            //Now we add the shape to the spatial component / body:
            spatialComp.collisionShapes = new Array();
            spatialComp.collisionShapes.push(shape);
             
            //Add the component to the entity:
            entity.addComponent( spatialComp, "Spatial" ); 			

			//Since we want to visualize the entity, we need a simple sprite renderer:
			var renderComp:SpriteRenderer = new SpriteRenderer(); 

			renderComp.scene = PBE.scene;
			renderComp.fileName = "../space/Images/asteroid01.png";
			renderComp.positionProperty  = new PropertyReference("@Spatial.position");
			renderComp.rotationProperty = new PropertyReference("@Spatial.rotation");
            renderComp.sizeProperty = new PropertyReference("@Spatial.size");
            renderComp.zIndex = 20;

			//Add the component to the entity:
			entity.addComponent( renderComp, "Render" )
            
            var hurtPlayerOnCollision:DamageEntityOnCollision = new DamageEntityOnCollision();
            hurtPlayerOnCollision.playerCollisionGroup = "Player";
            hurtPlayerOnCollision.damage = 34;
            entity.addComponent(hurtPlayerOnCollision, "HurtPlayerOnCollision");            
            
            var destroyOnCollision:DestroyEntityOnCollision = new DestroyEntityOnCollision();
            entity.addComponent(destroyOnCollision, "DestroyOnCollision");            

            return entity;
        }
        
		private function onLevelLoaded(e:Event):void 
		{
			loadImage();
            createBox2DDebugView();
		}
		
		private function loadImage():void
        {
            PBE.resourceManager.load("../space/Images/space.jpg", ImageResource, createBackground);
        }
        
        private function createBackground(image:ImageResource):void
        {
            var entity:IEntity = PBE.allocateEntity();
            var entName:String = PBE.nameManager.validateName("Background");
            entity.initialize(entName);
            
            var bgRenderer:ScrollingBitmapRenderer = new ScrollingBitmapRenderer();
            bgRenderer.srcBitmap = image.image;
            bgRenderer.width = 850;
            bgRenderer.height = 1024;
            bgRenderer.scene = PBE.scene;
			bgRenderer.layerIndex = 0;
			bgRenderer.alpha = 1.00;
			bgRenderer.x = -462;
			bgRenderer.y = -253;			
			bgRenderer.scrollSpeed.y = -55;

			entity.addComponent( bgRenderer, "Render" );
        }
                 
        private function onAddedToStage(evt:Event = null):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);

			//Initialize the engine
            PBE.startup(this);
            
			// Load embedded resources.
            new Resources();
            
			var sceneView:SceneView = new SceneView();
			
            PBE.initializeScene( sceneView, "Scene", null, Box2DManagerComponent );
            
			PBE.scene.screenPan( -30, 120 );
			
			PBE.levelManager.addEventListener(LevelEvent.LEVEL_LOADED_EVENT, onLevelLoaded);
			
            (PBE.spatialManager as Box2DManagerComponent).gravity = new Point(0, 0);
            if(!ExternalInterface.available)
            {
                LevelManager.instance.load("../space/levelDescriptions.xml", 1);
            }
                        
            PBE.templateManager.registerEntityCallback("Asteroid", createAsteroid);
            PBE.templateManager.registerEntityCallback("Bullet", createBullet);
		}
    }
}
